Skip to content

feat(daemon): report api_schema_version in /health + document API compatibility#103

Merged
wesm merged 2 commits into
kenn-io:mainfrom
mjacobs:feat/health-api-schema-version
Jun 10, 2026
Merged

feat(daemon): report api_schema_version in /health + document API compatibility#103
wesm merged 2 commits into
kenn-io:mainfrom
mjacobs:feat/health-api-schema-version

Conversation

@mjacobs

@mjacobs mjacobs commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

What

Closes the two follow-ups left open by #99: surface the API schema version in
/api/v1/health, and document the compatibility contract for the published
OpenAPI schema.

  • api_schema_version in /api/v1/health — the value stamped into the
    OpenAPI document's info.version (daemon.APISchemaVersion), so an external
    client can detect the HTTP API contract at runtime without parsing the
    committed schema. It's distinct from the existing schema_version, which is
    the DB/storage schema (meta.schema_version); the response doc comment spells
    out the difference so the two aren't conflated.
  • docs/reference/http-api.md — a Reference page covering how to obtain the
    schema (kata openapi / committed api/openapi.yaml), what the per-release
    snapshot is and isn't, the three version fields, and the compatibility
    expectations (additive changes unsignalled; breaking changes bump
    api_schema_version).

A design note worth a look

api_schema_version is optional in the schema even though current daemons
always send it. A version-detection field has to survive version skew: a client
generated from a schema that includes the field still needs to parse the
/health response of an older daemon that predates it, so an absent value
should read as "older than this field," not a parse failure. Making it required
would also have been a contract change that, by this PR's own documented rules,
should bump api_schema_version — keeping it additive avoids over-signalling.
The net schema delta is a single optional property; the required list is
unchanged.

The committed api/openapi.yaml is regenerated; the existing golden test keeps
it in lockstep with the routes.

Part of #97.

@roborev-ci

roborev-ci Bot commented Jun 6, 2026

Copy link
Copy Markdown

roborev: Combined Review (4a669b5)

Summary verdict: One medium documentation/schema compatibility issue needs resolution; no security issues were found.

Medium

  • docs/reference/http-api.md:69: The compatibility guidance says new optional response fields can appear without an api_schema_version change and clients should ignore unknown fields, but the published OpenAPI schemas use additionalProperties: false (for example api/openapi.yaml:1310). Strict clients or validators generated from the schema can reject additive response fields, making those changes breaking despite the documented policy.

    Fix: Either make response schemas permissive for additive fields, or change the compatibility guidance to require an API schema version bump for new response fields / explicitly require clients to disable strict response validation.


Panel: ci_default_security | Synthesis: codex, 7s | Members: codex_default (codex/default, done, 2m3s), codex_security (codex/security, done, 12s) | Total: 2m22s

@roborev-ci

roborev-ci Bot commented Jun 10, 2026

Copy link
Copy Markdown

roborev: Combined Review (3fb357b)

Medium: the PR changes the health response schema without bumping the published schema version.

  • Mediuminternal/daemon/openapi.go:9
    APISchemaVersion remains 0.1.0, but /api/v1/health now emits a new api_schema_version field and the published response schemas changed from closed to open. Clients generated from the previous committed 0.1.0 schema could strictly reject the new health response before they can inspect the version field, leaving two different wire/schema shapes under the same API schema version.
    Fix: Bump APISchemaVersion for this release, or introduce version discovery without changing the old health response shape for 0.1.0 clients.

Panel: ci_default_security | Synthesis: codex, 7s | Members: codex_default (codex/default, done, 3m9s), codex_security (codex/security, done, 16s) | Total: 3m32s

mjacobs and others added 2 commits June 10, 2026 10:44
…patibility

Surface the OpenAPI document's version (APISchemaVersion) at runtime so an
external client can detect the daemon's HTTP API contract without parsing the
committed schema. This closes the two follow-ups left open by kenn-io#99: the API
schema version in health output, and a documented compatibility contract.

- internal/api: add api_schema_version to HealthResponse, distinct from the
  existing schema_version (which is the DB/storage schema). The doc comment
  spells out the difference so the two version fields aren't conflated.
- internal/daemon: populate it from APISchemaVersion (the same const stamped
  into info.version of the OpenAPI doc), so health and schema never disagree.
- docs/reference: new "HTTP API schema" page covering how to obtain the schema
  (kata openapi / committed api/openapi.yaml), what the snapshot is and is not,
  the three version fields, and the compatibility expectations (additive
  changes unsignalled, breaking changes bump api_schema_version).
- api/openapi.yaml: regenerated; the golden test keeps it in lockstep.

Squashed commits:

- fix(api): make api_schema_version schema-optional (additive, no version
  bump): mark the field omitempty so its addition is a genuine additive
  change and a client treats an absent value as "daemon older than this
  field." Current daemons always populate it.
- fix(api): publish response schemas with additionalProperties:true:
  OpenAPIDocument relaxes every response-reachable object schema while
  request bodies keep their declared strictness, so strict clients don't
  break on additive optional response fields.
- docs(api): correct request-body strictness claim in compatibility notes:
  describe what the relaxation pass actually guarantees — it never loosens
  request schemas, which stay strict unless a type explicitly opts in.

Part of kenn-io#97.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The value is semver-shaped, which invites clients to infer ordering
semantics the policy never grants (e.g. "minor bump, probably safe").
State explicitly that clients compare for equality against the schema
they generated from and treat any other value as unverified.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@wesm wesm force-pushed the feat/health-api-schema-version branch from 3fb357b to caf054c Compare June 10, 2026 18:40
@roborev-ci

roborev-ci Bot commented Jun 10, 2026

Copy link
Copy Markdown

roborev: Combined Review (caf054c)

No Medium, High, or Critical findings were reported.

Both reviews found no security or qualifying severity issues.


Panel: ci_default_security | Synthesis: codex, 5s | Members: codex_default (codex/default, done, 6m5s), codex_security (codex/security, done, 4m8s) | Total: 10m18s

@wesm wesm merged commit cb98442 into kenn-io:main Jun 10, 2026
7 checks passed
@mjacobs mjacobs deleted the feat/health-api-schema-version branch June 11, 2026 23:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants